package net.jumpengine.bean;

import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.sun.javafx.geom.Rectangle;

import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseButton;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import net.jumpengine.M;
import net.jumpengine.enume.TableDataSource;
import net.jumpengine.inter.IAction;
import net.jumpengine.inter.ITable;
import net.jumpengine.po.Column;
import net.jumpengine.po.TableData;
import net.jumpengine.util.UComm;
import net.jumpengine.util.UDraw;

/**
 * 列表显示组件
 * <br /><br />
 * <b>作者:&nbsp;</b>张天文 <br />
 * <b>日期:&nbsp;</b>2020年3月25日 上午11:17:59<br />
 * @date
 */
public class TableBase<T> extends ClickBase implements ITable{
	protected String dateFormat="yyyy-MM-dd kk:mm:ss"; 
	protected String numberFormat="###,###,###,###.00";
	protected String[] booleanFormat=new String[]{"是","否"};
	
	private SimpleDateFormat sdf=new SimpleDateFormat();
	private DecimalFormat df=new DecimalFormat(numberFormat);
	
	/** 当align为左对齐或右对齐,文字左间距或右间距 */
	protected int padding=3;
	
	protected List<Column> columns=new ArrayList<Column>();
	
	protected Object[][] data;
	protected List<Map<String,?>> dataList;
	protected TableData<T> tableData;
	protected TableDataSource source;
	
	protected Font columnFont=UDraw.getFont("黑体", 20, true, false);
	protected Color columnColor=Color.WHITE,columnBackColor=Color.web("#825A33");
	protected Font textFont=UDraw.getFont("黑体", 20, false, false);
	protected Color oddColor=Color.web("#333333"),textColor=Color.web("#E3E3E3");
	protected Color oddBackColor=Color.web("#DABFA5"),textBackColor=Color.web("#AA7642");
	
	protected int selRow=-1,rowHeight;
	
	private int cx,cy;
	private Column col;

	public TableBase(int x, int y, int width) {
		this(x, y, width, 0);
	}
	
	public TableBase(int x, int y, int width, int index) {
		super(x, y, width, 0, index);
		
		action=new IAction() {
			@Override
			public void handle(int mx, int my, MouseButton button, Base base) {
				if(my<rowHeight-y)return;
				selRow=((my-y)/rowHeight);
			}
		};
	}
	
	@Override
	public Rectangle getInnerRect() {
		return null;
	}

	@Override
	public void draw(GraphicsContext g) {
		String result;
		rowHeight=UDraw.fontHeight(columnFont)+padding*2;
		
		g.setFill(columnBackColor);
		g.fillRect(x, y, width, rowHeight);
		cx=x;
		cy=y+padding;
		g.setFill(columnColor);
		g.setFont(columnFont);
		for(int i=0;i<columns.size();i++) {
			col=columns.get(i);
			UDraw.boldString(col.getName(), cx+padding, cy, g);
			col.setLeft(cx);
			cx+=col.getMathWidth();
		}
		
		int size=dataSize();
		
		for(int row=0;row<size;row++) {
			cy=y+(row+1)*rowHeight;
			
			if(selRow==row+1) {
				g.setFill(UDraw.antiColor(row % 2==0?oddBackColor:textBackColor));
			}else {
				g.setFill(row % 2==0?oddBackColor:textBackColor);
			}
			g.fillRect(x, cy, width, rowHeight);
			for(int colNo=0;colNo<columns.size();colNo++) {
				col=columns.get(colNo);
				if(col.isNo()) {
					result=row+1+"";
				}else {
					result=loadOneData(row, colNo, col);
				}
				if(result==null)continue;
				if(selRow==row+1) {
					g.setFill(UDraw.antiColor(row % 2==0?oddColor:textColor));
				}else {
					g.setFill(row % 2==0?oddColor:textColor);
				}
				g.fillText(result, col.getLeft()+padding, cy+padding);
			}
		}
		height=cy+rowHeight;
	}
	
	public TableBase<T> addColumn(Column col) {
		addColumn(col,true);
		return this;
	}
	public TableBase<T> addColumn(Column col,boolean useOne) {
		if(col.isNo()) {
			if(!UComm.isNull(columns)) {
				Column tmp=columns.get(0);
				if(tmp.isNo()) {
					M.l().error(TableBase.class,"[addColumn]该表格已经有序号列,不能再添加序号列!");
					return this;
				}
			}
			columns.add(0, col);
		}else {
			columns.add(col);
		}
		if(useOne)columnMathWidth();
		return this;
	}
	
	public TableBase<T> addColumns(String...columnNames) {
		if(columnNames==null || columnNames.length==0)return this;
		for(String col:columnNames) {
			columns.add(new Column(col));
		}
		columnMathWidth();
		return this;
	}
	
	public void addColumns(Column...columns) {
		if(columns==null || columns.length==0)return;
		for(Column col:columns)addColumn(col);
		columnMathWidth();
	}
	
	private void columnMathWidth() {
		if(columns==null || columns.size()==0)return;
		int size=dataSize();
		if(size<0)return;
		int count=2;
		if(size>0)count=(size+"").length();
		List<Column> split=new ArrayList<>();
		List<Column> other=new ArrayList<>();
		int cwidth=width,tmp;
		for(Column col:columns) {
			if(col.isNo()) {
				tmp=(int) (count*textFont.getSize()+padding*2);
				cwidth-=tmp;
				col.setMathWidth(tmp);
			}else if(col.getWidth()==0) {
				other.add(col);
			}else if(col.getWidth()==-1) {
				split.add(col);
			}else {
				tmp=col.getWidth();
				col.setMathWidth(tmp);
				cwidth-=tmp;
			}
		}
		size=split.size()>0?cwidth/split.size():cwidth;
		for(Column col:split) {
			col.setMathWidth(size);
			cwidth-=size;
		}
		size=other.size()>0?cwidth/other.size():cwidth;
		for(Column col:other) {
			col.setMathWidth(size);
		}
	}
	
	private int dataSize() {
		if(source==null)return -1;
		if(source==TableDataSource.array && data!=null)return data.length;
		if(source==TableDataSource.listMap && dataList!=null)return dataList==null?0:dataList.size();
		if(source==TableDataSource.tableData)return tableData.size();
		return -2;
	}
	
	private String loadOneData(int row,int col,Column column) {
		if(source==null) {
			return null;
		}else {
			Object obj=null;
			if(source==TableDataSource.array && data!=null) {
				obj=data[row][col];
			}else if(source==TableDataSource.listMap && dataList!=null) {
				obj=dataList.get(row).get(column.getKey());
			}else if(source==TableDataSource.tableData) {
				obj=tableData.getDate(row, col,column);
			}
			return formatObject(obj,column);
		}
	}
	
	private String formatObject(Object obj,Column column) {
		if(obj==null)return null;
		StringBuffer sbr=new StringBuffer();
		if(obj instanceof Number) {
			df.format(obj, sbr, new FieldPosition(NumberFormat.FRACTION_FIELD));
			return sbr.toString();
		}else if(obj instanceof Date) {
			sdf.applyPattern(dateFormat);
			return sdf.format((Date)obj);
		}else if(obj instanceof Boolean) {
			Boolean b=(Boolean) obj;
			return b?booleanFormat[0]:booleanFormat[1];
		}else {
			return obj.toString();
		}
	}
	
	/**
	 * 设置字体, 列头字体会加粗, 行内字体为普通,行的高度为size+padding*2
	 * @param name 字体名称
	 * @param size 尺寸
	 */
	public void setFont(String name,int size) {
		columnFont=UDraw.getFont(name, size, true, false);
		textFont=UDraw.getFont(name, size, false, false);
	}

	public String getDateFormat() {
		return dateFormat;
	}

	public void setDateFormat(String dateFormat) {
		this.dateFormat = dateFormat;
	}

	public String getNumberFormat() {
		return numberFormat;
	}

	public void setNumberFormat(String numberFormat) {
		this.numberFormat = numberFormat;
		df=new DecimalFormat(numberFormat);
	}

	public int getPadding() {
		return padding;
	}

	public void setPadding(int padding) {
		if(padding>=0 && padding<width) {
			this.padding = padding;
		}else {
			M.l().error(TableBase.class,"[setPadding(int)]padding:",padding," 超出0-table.width范围");
		}
	}

	public List<Column> getColumns() {
		return columns;
	}

	public void setColumns(List<Column> columns) {
		this.columns = columns;
	}

	public Object[][] getData() {
		return data;
	}

	public void setData(Object[][] data) {
		this.data = data;
		source=TableDataSource.array;
		columnMathWidth();
	}

	public List<Map<String, ?>> getDataList() {
		return dataList;
	}

	public void setDataList(List<Map<String, ?>> dataList) {
		this.dataList = dataList;
		source=TableDataSource.listMap;
		columnMathWidth();
	}

	public TableData<T> getTableData() {
		return tableData;
	}

	public void setTableData(TableData<T> tableData) {
		this.tableData = tableData;
		source=TableDataSource.tableData;
		columnMathWidth();
	}

	public TableDataSource getSource() {
		return source;
	}

	public Font getColumnFont() {
		return columnFont;
	}

	public void setColumnFont(Font columnFont) {
		this.columnFont = columnFont;
	}

	public Color getColumnColor() {
		return columnColor;
	}

	public void setColumnColor(Color columnColor) {
		this.columnColor = columnColor;
	}

	public Color getColumnBackColor() {
		return columnBackColor;
	}

	public void setColumnBackColor(Color columnBackColor) {
		this.columnBackColor = columnBackColor;
	}

	public Font getTextFont() {
		return textFont;
	}

	public void setTextFont(Font textFont) {
		this.textFont = textFont;
	}

	public Color getOddColor() {
		return oddColor;
	}

	public void setOddColor(Color oddColor) {
		this.oddColor = oddColor;
	}

	public Color getTextColor() {
		return textColor;
	}

	public void setTextColor(Color textColor) {
		this.textColor = textColor;
	}

	public Color getOddBackColor() {
		return oddBackColor;
	}

	public void setOddBackColor(Color oddBackColor) {
		this.oddBackColor = oddBackColor;
	}

	public Color getTextBackColor() {
		return textBackColor;
	}

	public void setTextBackColor(Color textBackColor) {
		this.textBackColor = textBackColor;
	}

	public int getSelRow() {
		return selRow;
	}

}
